class OliveProj_RebundGun extends UTProjectile
	placeable
	config(Weapon);

var float GravityScale;

var() const config protected int   MaxBounceCount;

var protected transient int BounceCount;

var() protected float   VelocityDampingFactor;

var() protected float   Bounciness;

var() protected float   StopSimulatingVelocityThreshhold;

var config float MaxExplosionDelay;
//>= 1, explode
var transient float CurrentDamageTaken;

var float   VelocityDampingFactorInWater;

var transient vector BounceHitNormal;

//simulated function PostBeginPlay()
//{
//	Acceleration.X = 0;
//	Acceleration.Y = 0;
//	Acceleration.Z = GetGravityZ() * GravityScale;
//	super.PostBeginPlay();
//}

//event Init(Vector Direction)
//{
//	super.Init(Direction);
//	Acceleration.X = 0;
//	Acceleration.Y = 0;
//	Acceleration.Z = GetGravityZ() * GravityScale;

//	`log(GetFuncName()@Velocity.X@Velocity.Y@Velocity.Z);
//}

simulated function DoExplosion()
{
	Explode(Location, BounceHitNormal);
}

simulated function bool ShouldBounce(Actor Touched, vector HitNormal, optional PrimitiveComponent HitComponent)
{
    if( (Touched == None) || (Base != None) )
    {
        return FALSE;
    }

    // cannot collide with instigator until it has bounced once
    // also don't allow projectiles to collide while spawning on clients
    // because if that were accurate, the projectile would've been destroyed immediately on the server
    // and therefore it wouldn't have been replicated to the client
    if ((/*Touched == Instigator || */(Role < ROLE_Authority && !bBegunPlay))/* && BounceCount == 0*/)
    {
		`log(GetFuncName()@Touched@"false");
        return FALSE;
    }

    if( Touched.bWorldGeometry || Touched.bBlockActors )
    {
        return TRUE;
    }

    return FALSE;
}

simulated function Bounce(Vector HitLocation, Vector HitNormal, Actor Other)
{
	local float BounceAngle;
	local vector NormalVel;

	BounceHitNormal = HitNormal;
    if( !bBounce)
    {
        StopBounce();
        return;
    }

	if(FluidSurfaceActor(Other) != none)
	{
		//if we hit in the water, do not bounce
		Velocity.Z = 0.f;
		Velocity *= VelocityDampingFactorInWater;
		//`log("Hit in the water"@Velocity.X@Velocity.Y@Velocity.Z);
		Explode(Location, BounceHitNormal);
		return ;
	}
    BounceCount++;

	//if(CurveStaticMeshActor(Other) != none && !CurveStaticMeshActor(Other).bDisableCurveBounce)
	//{
	//	//todo 
	//	Normal(HitNormal) + Normal(Velocity);
	//}
	//else
	//{
		// bounce off wall with damping
		Velocity -= (1.f + Bounciness) * HitNormal * (Velocity Dot HitNormal);
		Velocity *= VelocityDampingFactor;
	//}

	NormalVel = -Normal(Velocity);
	BounceAngle = NormalVel dot HitNormal;
	CurrentDamageTaken += BounceAngle;
	if (CurrentDamageTaken > 0.9)
    {
        DoExplosion();
    }

    // should we stop simulating?
    if( VSize(Velocity) < StopSimulatingVelocityThreshhold )
    {
        StopBounce();
    }

	if (BounceCount == 1)
    {
		SetTimer(MaxExplosionDelay, false, nameof(DoExplosion));
    }
}

simulated function HandleCollision( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal )
{
	//`log(self@"** hit!"@Other@OtherComp@HitNormal@HitLocation);
    if( Other != None && (FluidSurfaceActor(Other) != none || ShouldBounce(Other, HitNormal)) && Physics == PHYS_Projectile )
    {
        // a bit of a hack, massage data for pawns
        if ( (Pawn(Other) != None) && (SkeletalMeshComponent(OtherComp) != None) )
        {
            HitNormal = HitLocation - Other.Location;
            HitNormal.Z = 0.f;
            HitNormal = Normal(HitNormal);
        }
        Bounce(HitLocation, HitNormal, Other);
    }
}

simulated function StopBounce()
{
    bBounce = FALSE;
    if (Role == ROLE_Authority )
    {
        Explode(Location, BounceHitNormal);
    }
}


simulated singular event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal )
{
	//`log(GetFuncName()@Other);
    // Ignore touches on fluid surface or physics volumes
    if(FluidSurfaceActor(Other) != None || PhysicsVolume(Other) != None)
    {
        return;
    }

	ImpactedActor = Other;
    HandleCollision( Other, OtherComp, HitLocation, HitNormal );
}

simulated function HitWall( vector HitNormal, Actor Wall, PrimitiveComponent WallComp )
{
    HandleCollision( Wall, WallComp, Location, HitNormal );
}

DefaultProperties
{
	GravityScale=1f
	Damage=600
	DamageRadius=300

	StopSimulatingVelocityThreshhold=40
	Bounciness=1.f
	VelocityDampingFactor=1.f
	ProjFlightTemplate=ParticleSystem'WP_RocketLauncher.Effects.P_WP_RocketLauncher_Smoke_Trail'
	ProjExplosionTemplate=ParticleSystem'WP_RocketLauncher.Effects.P_WP_RocketLauncher_RocketExplosion'

	bBounce=true
	Speed=1000
	Begin Object Class=SkeletalMeshComponent Name=ESkeletalMeshComponent
		SkeletalMesh=SkeletalMesh'KismetGame_Assets.Anims.SK_Jazz'
		BlockRigidBody=TRUE
		bUpdateSkelWhenNotRendered=false
		Translation=(Z=0.0)
		Scale=0.2f
	End Object
	Components.Add(ESkeletalMeshComponent)
}
